package controllers

import (
	"errors"
	"kms-backend/config"
	"kms-backend/utils/logs"
	"net/http"

	"github.com/dotbalo/kubeutils/kubeutils"
	"github.com/gin-gonic/gin"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

// 定义全局的数据结构
// 绑定Get方法传递的数据，需要使用form形式
type BasicInfo struct {
	ClusterId  string      `json:"clusterId" form:"clusterId"`
	Namespace  string      `json:"namespace" form:"namespace"`
	Name       string      `json:"name" form:"name"`
	Item       interface{} `json:"item"`
	DeleteList []string    `json:"deletelist"`
}

type Info struct {
	BasicInfo
	ReturnData    config.ReturnData
	LabelSelector string `json:"labelselector" form:"labelselector"`
	FieldSelector string `json:"fieldSelector" form:"fieldSelector"`
	// 判断是否强制删除
	Force bool `json:"force" form:"force"`
}

// 创建方法
func (c *Info) Create(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	err := kubeUtilsInterface.Create(c.Namespace)
	if err != nil {
		msg := "创建失败: " + err.Error()
		c.ReturnData.Message = msg
		c.ReturnData.Status = 400
		logs.Error(nil, msg)
	}
	r.JSON(200, c.ReturnData)
}

// 更新方法
func (c *Info) Update(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	err := kubeUtilsInterface.Update(c.Namespace)
	if err != nil {
		msg := "更新失败: " + err.Error()
		c.ReturnData.Message = msg
		c.ReturnData.Status = 400
		logs.Error(nil, msg)
	}
	r.JSON(200, c.ReturnData)
}

// List方法
func (c *Info) List(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	// List需要3个参数：namespace、lableselector、fieldselector
	// 直接返回items 和error
	items, err := kubeUtilsInterface.List(c.Namespace, c.LabelSelector, c.FieldSelector)
	if err != nil {
		msg := "查询失败: " + err.Error()
		c.ReturnData.Message = msg
		c.ReturnData.Status = 400
		logs.Error(nil, msg)
	} else {
		c.ReturnData.Data = make(map[string]interface{})
		c.ReturnData.Data["items"] = items
	}
	r.JSON(200, c.ReturnData)
}

// Get方法
func (c *Info) Get(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	item, err := kubeUtilsInterface.Get(c.Namespace, c.Name)
	if err != nil {
		msg := "查询失败: " + err.Error()
		c.ReturnData.Message = msg
		c.ReturnData.Status = 400
		logs.Error(nil, msg)
	} else {
		c.ReturnData.Data = make(map[string]interface{})
		c.ReturnData.Data["items"] = item
	}
	r.JSON(200, c.ReturnData)
}

// Delete方法
func (c *Info) Delete(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	var gracePeriodSeconds int64
	if c.Force {
		// 强制删除, 0 表示立即删除
		var s int64 = 0
		gracePeriodSeconds = s
	}
	// 需要3个参数: namespace name int64
	// int64 表示是否强制删除的参数
	err := kubeUtilsInterface.Delete(c.Namespace, c.Name, &gracePeriodSeconds)
	if err != nil {
		msg := "删除失败: " + err.Error()
		c.ReturnData.Message = msg
		c.ReturnData.Status = 400
		logs.Error(nil, msg)
	}
	r.JSON(200, c.ReturnData)
}

// Delete列表方法
func (c *Info) DeleteList(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	var gracePeriodSeconds int64
	if c.Force {
		// 强制删除, 0 表示立即删除
		var s int64 = 0
		gracePeriodSeconds = s
	}
	// 需要3个参数: namespace name int64
	// int64 表示是否强制删除的参数
	err := kubeUtilsInterface.DeleteList(c.Namespace, c.BasicInfo.DeleteList, &gracePeriodSeconds)
	if err != nil {
		msg := "删除失败: " + err.Error()
		c.ReturnData.Message = msg
		c.ReturnData.Status = 400
		logs.Error(nil, msg)
	}
	r.JSON(200, c.ReturnData)
}

// 优化代码使用的接口工具kubeutils需要一个kubeconfig，此处用构造函数获取kubeconfig
func NewInfo(r *gin.Context, info *Info, returnDataMsg string) (kubeconfig string) {

	// 绑定前端传递的json数据，也需要根据调用方法来区别，因为绑定方法不一样
	requestMethod := r.Request.Method
	var err error
	info.ReturnData.Message = returnDataMsg
	info.ReturnData.Status = 200
	if requestMethod == "GET" {
		err = r.ShouldBindQuery(&info)
	} else if requestMethod == "POST" {
		err = r.ShouldBindJSON(&info)
	} else {
		err = errors.New("不支持该请求方式")
	}

	if err != nil {
		msg := "绑定basicInfo时请求出错" + err.Error()
		info.ReturnData.Message = msg
		info.ReturnData.Status = 400
		logs.Error(nil, msg)
		r.JSON(http.StatusOK, info.ReturnData)
		return
	}

	// 默认去default命名空间
	if info.Namespace == "" {
		info.Namespace = "default"
	}

	// 获取kubeconfig
	kubeconfig = config.ClusterKubeConfig[info.ClusterId]
	return kubeconfig
}

// 实现一个基础功能，来生成clientSet
func BasicInit(r *gin.Context, item interface{}) (clientSet *kubernetes.Clientset, basicInfo BasicInfo, err error) {
	// 初始化数据
	basicInfo = BasicInfo{}
	basicInfo.Item = item
	// 绑定前端传递的json数据，也需要根据调用方法来区别，因为绑定方法不一样
	requestMethod := r.Request.Method
	if requestMethod == "GET" {
		err = r.ShouldBindQuery(&basicInfo)
	} else if requestMethod == "POST" {
		err = r.ShouldBindJSON(&basicInfo)
	} else {
		err = errors.New("不支持该请求方式")
	}

	if err != nil {

		msg := "绑定basicInfo时请求出错" + err.Error()
		logs.Error(nil, msg)
		return nil, basicInfo, err
	}

	// 默认去default命名空间
	if basicInfo.Namespace == "" {
		basicInfo.Namespace = "default"
	}

	// 获取kubeconfig
	kubeconfig := config.ClusterKubeConfig[basicInfo.ClusterId]
	restConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(kubeconfig))

	if err != nil {
		msg := "解析kubeconfig出错" + err.Error()
		logs.Error(nil, msg)
		return nil, basicInfo, err
	}
	// 创建clientset客户端工具
	clientSet, err = kubernetes.NewForConfig(restConfig)
	if err != nil {
		msg := "创建clientset失败" + err.Error()
		logs.Error(nil, msg)
		return nil, basicInfo, err
	}

	return clientSet, basicInfo, nil
}
